// $Id$
// This file contains scripts to run on any page that contains a product with
// a buy link. This includes dynamically showing/hiding content based on users'
// selections, updating the estimated price when options are changed, and
// dispatching requests to the UltraCart API for adding to cart.

/*
 * Converts a plain number to use commas every 3 digits.
 *
 * @param x - the number to add commas to
 */
DSC.numberWithCommas = function (x) {
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
};

/*
 * Trims the whitespace off of the front and back of a string, without touching
 * any 'inner' whitespace.
 *
 * @param str - the string to trim.
 */
DSC.trim = function(str) {
  return str.replace(/^\s+/, '').replace(/\s+$/, '');
}

/*
 * Sort the rows in the cross-reference tables by manufacturer.
 */
DSC.sortCrossRef = function() {
  $('.cross-ref table').each(function() {
    // sort alphanumerically by contents of first <td> in each <tr>
    var $trs = $(this).find('tr');
    var headers = $trs.slice(0, 2); // ignore the table headers
    var rows = $trs.slice(2);
    var html = '';
    rows.sort(function(a, b) {
      var aMan = DSC.trim($(a).find('td').eq(0).html()).toLowerCase();
      var bMan = DSC.trim($(b).find('td').eq(0).html()).toLowerCase();
      return aMan.localeCompare(bMan);
    });
    // rows are now sorted, put them back into their parent elements
    var i, len, str, $tmp;
    // build headers
    for (i = 0, len = headers.length; i < len; i += 1) {
      $tmp = $('<div></div>');
      str = $tmp.append($(headers[i])).html();
      html += str;
    }
    // build rows
    for (i = 0, len = rows.length; i < len; i += 1) {
      $tmp = $('<div></div>');
      str = $tmp.append($(rows[i])).html();
      html += str;
    }
    $(this).html(html);
  });
}

/*
 * Sort the options of each <select> element by first number. This is mainly
 * for length selectors in product buy forms.
 */
DSC.sortOptions = function() {
  $('select').each(function() {
    var items = this.options.length,
        tmpArray = new Array(items),
        i;
    for (i = 0; i < items; i += 1) {
      tmpArray[i] = new Option(this.options[i].text, this.options[i].value);
    }
    tmpArray.sort(function(a, b) {
      // sort by first float
      var aFloat = parseFloat(a.text),
          bFloat = parseFloat(b.text);
      aFloat = isNaN(aFloat) ? -1 : aFloat;
      bFloat = isNaN(bFloat) ? -1 : bFloat;
      return aFloat - bFloat;
    });
    for (i = 0; i < items; i++) {
      // replace the existing options with the sorted ones
      this.options[i] = new Option(tmpArray[i].text, tmpArray[i].value);
    }
  });
};

/*
 * When a user adds or removes elements from their cart, we should update the
 * cart button with the appropriate item count.
 */
DSC.updateCartQuantity = function () {
  var quantity = 0,
      items = ultraCart.getCart().items,
      item,
      i;
  // count items
  for (i = items.length - 1; item = items[i]; i -= 1) {
    quantity += item.quantity;
  }
  if (quantity > 0) {
    // only show if there are items in the cart
    $('#cart span').html('Cart (' + quantity + ')');
  }
};

/*
 * Behaviors to run on page load.
 */
$(document).ready(function() {
  var loaderURI = '/html5/img/icons/ajax-loader.gif';
  var checkURI = '/html5/img/icons/checkmark-16.png';

  // pdf links should open in new page
  $('.pdf').click(function() {window.open(this.href); return false;});

  // Selecting a length will swap out any default information
  // and replace it with child-specific information.
  $('.product select').change(function(event) {
    var $this = $(this), // keep a reference to $(this) for closure access
        $parent = $this.parents('.product'),
        $default = $parent.find('.default-info'),
        $aux = $parent.find('.aux-info'),
        $all = $default.add($aux),
        varID = $this.val().replace('\.', '_'),
        $show,
        $hide,
        length;
    if (this.selectedIndex === 0) {
      // Default is selected
      $hide = $aux; // hide auxiliary information
      $show = $default; // show default information
    } else {
      // Variation is selected
      $hide = $all; // hide all information
      $show = $aux.filter('.' + varID); // show aux info for selection
    }
    length = $hide.length;
    $hide.fadeOut(200, function() {
      // called for every element in $hide
      if ((length -= 1) > 0) {
        return; // some elements are still fading out
      } else {
        // done fading out all elements
        length = $show.length;
        $show.css('background-color', '#FFFFCC').fadeIn(200, function() {
          if ((length -= 1) > 0) {
            return; // some elements are still fading in
          } else {
            // done fading in, highlight
            $show.animate({backgroundColor: '#FFFFFF'}, 750, 'linear');
          }
        });
      }
    });
  });

  // Re-calculate the estimated total if either the select or
  // quantity input changes values.
  $('.product select, .product input').change(function(event) {
    var $parent = $(this).parents('.product'),
        $buy = $(this).parents('.buy'),
        $container = $buy.find('.total .num').eq(0),
        quantity = parseInt($buy.find('.quantity').val()),
        $pricing,     // cache the pricing section
        $quantities,  // cache the quantity elements
        $costs,       // cache the cost elements
        tierIndex,    // which tier we are currently examining
        tierCost,     // parsed float
        tierQuantity, // parsed int
        cost,         // final price for multiplication
        total,        // total cost to update the display with
        varID;        // the variation item ID, if it exists
    if (isNaN(quantity)) {
      $buy.find('.quantity').val(1);
      quantity = parseInt($buy.find('.quantity').val());
    }
    $buy.find('.add-to-cart span').css('background-image', 'none');
    $buy.find('.add-to-cart button').html('Add to Cart');
    if ($buy.find('select').length) {
      // multiple variations; pick the correct pricing table
      if ($buy.find('select')[0].selectedIndex !== 0) {
        // Child selected; snag the ID
        varID = $buy.find('select').val().replace('\.', '_');
        $pricing = $parent.find('.pricing .' + varID);
      } else {
        // Default is selected; clear the price
        $parent.find('.buy .total .num').eq(0).html('');
        return;
      }
    } else {
      $pricing = $parent.find('.pricing');
    }
    $quantities = $pricing.find('.tier-quantity');
    $costs = $pricing.find('.tier-cost');
    if ($quantities.length > 0) {
      // we have some tiers to work with
      for (tierIndex = 0; tierIndex < $quantities.length; tierIndex += 1) {
        tierQuantity = parseInt($quantities.eq(tierIndex).html().replace(/\s*/, ''));
        tierCost = parseFloat($costs.eq(tierIndex).html().replace(/[\s\$]*/, ''));
        if (quantity >= tierQuantity) {
          // item quantity qualifies for this tier, update price
          cost = tierCost;
        } else {
          // item does not qualify for this tier, get out of loop
          break;
        }
      }
    } else {
      // simply grab the only price
      cost = parseFloat($costs.eq(0).html().replace(/[\s\$]*/, ''));
    }
    total = '$' + DSC.numberWithCommas((quantity * cost).toFixed(2)); // format the total
    $container.fadeOut(100, function() {
      // done fading out
      $container.html(total).fadeIn(100);
    });
  });

  // on submit, highjack form and add to cart without leaving page.
  // also, update the cart quantity and show a check mark if successful
  $('.buy form').submit(function(event) {
    try {
      event.preventDefault();
      var $this = $(this),
          $status = $this.find('.add-to-cart span'),
          $select = $this.find('select'),
          quantity = parseInt($this.find('input.quantity').val()),
          itemID,
          errors,
          error;
      if ($select.length === 0) {
        // no variations, use regular item id
        itemID = $this.find('input[name=add]').attr('value').replace(/\s/g, '');
      } else {
        if ($select[0].selectedIndex === 0) {
          // default is selected, so focus on the <select> element and return
          $select.focus();
          return;
        } else {
          itemID = $select.val();
        }
      }
      // show the spinner while we talk to UltraCart
      $status.css('background-image', "url('" + loaderURI + "')");
      ultraCart.addItems([{itemId: itemID, quantity: quantity}], {
        async: true,
        onComplete: function(results) {
          // finished talking
          if (results.errors.length === 0) {
            // no errors, stop the spinner and show success
            $status.css('background-image', "url('" + checkURI + "')");
            $this.find('button').html('Added to Cart');
            DSC.updateCartQuantity();
          } else {
            for (error in results.errors) {
              console.log(error);
            }
          }
        }
      });
    } catch (e) {
      console.log('Add to cart' + e);
    }
  });

  // sort select options
  if (!$.browser.msie) {
    DSC.sortOptions();
  }

  // trigger changes on the inputs to calculate any possible totals
  $('.product input').trigger('change');

  // register all sets of gallery links with the jQuery lightbox plugin
  $(function() {
  	$('a.lightbox').reverse().lightBox();
  });

  // sort the cross reference tables by manufacturer
  DSC.sortCrossRef();
  DSC.preloadImages(loaderURI, checkURI);

});